// Copyright 2011, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_FILE_LINUX_ACFILE_IMPL_HPP_
#define LIBV_FILE_LINUX_ACFILE_IMPL_HPP_

#ifndef __linux__
# error "This header should be used in Linux only."
#endif

#include <aio.h>
#include <assert.h>
#include <string>
#include <libv/stdint.h>
#include <libv/file/basic_file.h>



namespace libv
{

bool ACFile::OpenImpl(const ::std::string& file_path,
                      const int open_type,
                      const bool enable_read_ahead_caching,
                      const bool read_only) const
{
    return BasicFile::BasicOpen(file_path,
                                open_type,
                                enable_read_ahead_caching,
                                0,
                                read_only);
}



bool ACFile::WriteImpl(const fpos64& offset,
                       const void* data,
                       const uint32_t data_size,
                       ACFile::RequestCompletionHandle* completion_handle)
{
    aiocb a = { 0 };
    a.aio_fildes = file_handle_;
    a.aio_offset = offset;
    // Конечно, это плохое приведение типа, но aiocb используется и при чтении
    // и при записи и из-за этого volatile нужен и для записи, хотя буфер
    // не изменится.
    a.aio_buf = static_cast<volatile void*>(const_cast<void*>(data));
    a.aio_nbytes = data_size;
    RequestCompletionHandle c(file_handle_, a, data_size,
                              RequestCompletionHandle::WRITING);

    const bool result = ( ::aio_write(c.request_handle_) == 0 );
    last_error_ = errno;

    if ( result )
        *completion_handle = c;

    return result;
}



bool ACFile::ReadImpl(const fpos64& offset,
                      volatile void* buffer,
                      const uint32_t buffer_size,
                      ACFile::RequestCompletionHandle* completion_handle) const
{
    aiocb a = { 0 };
    a.aio_fildes = file_handle_;
    a.aio_offset = offset;
    a.aio_buf = buffer;
    a.aio_nbytes = buffer_size;
    RequestCompletionHandle c(file_handle_, a, buffer_size,
                              RequestCompletionHandle::READING);

    const bool result = ( ::aio_read(c.request_handle_) == 0 );
    last_error_ = errno;

    if ( result )
        *completion_handle = c;

    return result;
}

}  // libv

#endif  //  LIBV_FILE_LINUX_ACFILE_IMPL_HPP_
